package com.quanyan.orderpay.web;

import com.quanyan.common.encrypt.AESCoder;
import com.quanyan.common.utils.*;
import com.quanyan.order.mapper.UOrderMapper;
import com.quanyan.order.vo.OrderQueryRespVo;
import com.quanyan.orderpay.component.OrderPayRedisTemplate;
import com.quanyan.orderpay.constants.OrderMqConstants;
import com.quanyan.orderpay.entity.PaySuccessData;
import com.quanyan.orderpay.service.OrderProcessService;
import com.quanyan.orderpay.vo.request.ChinaumsOrderQueryReqVo;
import com.quanyan.orderpay.vo.request.ChinaumsPayNotifyReqVo;
import com.quanyan.orderpay.vo.response.ChinaumsOrderQueryRespVo;
import com.quanyan.orderpay.vo.response.ChinaumsPayNotifyRespVo;
import com.quanyan.pay.entity.TSNRecord;
import com.quanyan.pay.enums.TradeTypeEnum;
import com.quanyan.pay.service.TsnService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;

/**
 * 银联商户
 */
@RestController
@RequestMapping("/api/pay/chinaums")
public class ChinaumsController {
    private Logger logger = LoggerFactory.getLogger(ChinaumsController.class);
    private static final String apiKey = AESCoder.decodeContent("6dc2b74790e10e6b1c94d9db21e33d0a2646849accab772c269c29e5a5096e78");

    @Autowired
    private UOrderMapper uOrderMapper;
    @Autowired
    private TsnService tsnService;
    @Autowired
    private OrderProcessService orderProcessService;
    @Autowired
    private OrderPayRedisTemplate orderPayRedisTemplate;


    /**
     * 银联支付订单查询接口
     *
     * @return
     */
    @RequestMapping(value = "/orderQuery", method = RequestMethod.POST)
    public String orderQuery(@RequestBody ChinaumsOrderQueryReqVo vo) {
        ChinaumsOrderQueryRespVo respVo = null;
        ValidationResult result = ValidationUtils.validateEntity(vo);
        if (result.hasErrors()) {
            respVo = new ChinaumsOrderQueryRespVo(202, result.getErrorDesc());
            respVo.setNonceStr(StringUtil.genRandomCode(32, false));
            String sign = SignatureUtils.getWxSign(respVo, apiKey);
            respVo.setSign(sign);
            return GsonUtils.toJson(respVo);
        }

        String orderNo = vo.getOrderNo();
        String neetCheckSign = vo.getSign();
        vo.setSign(null);
        String rightSign = SignatureUtils.getWxSign(vo, apiKey);
        if (!rightSign.equals(neetCheckSign)) {
            respVo = new ChinaumsOrderQueryRespVo(201, "签名不正确");
            respVo.setNonceStr(StringUtil.genRandomCode(32, false));
            String sign = SignatureUtils.getWxSign(respVo, apiKey);
            respVo.setSign(sign);
            return GsonUtils.toJson(respVo);
        }
        // 将已读状态放入缓存
        orderPayRedisTemplate.setex("IS_SCAN_ORDER_NO_" + orderNo, "1", 30*60); // 半小时过期

        OrderQueryRespVo orderQueryRespVo = uOrderMapper.getOrderQueryByOrderNo(orderNo);
        respVo = new ChinaumsOrderQueryRespVo(200, "返回成功");
        respVo.setNonceStr(StringUtil.genRandomCode(32, false));
        respVo.setOrderNo(orderNo);
        if (orderQueryRespVo == null) {
            respVo.setTradeState("01"); // 订单不存在
            String sign = SignatureUtils.getWxSign(respVo, apiKey);
            respVo.setSign(sign);
            return GsonUtils.toJson(respVo);
        }
        byte orderState = orderQueryRespVo.getOrderState();
        switch (orderState) {
            case 0: // 订单等待支付
                respVo.setTradeState("00");
                break;
            case 1: // 订单已支付
                respVo.setTradeState("02");
                break;
            case 2:
            case 3: // 订单已关闭或已取消
                respVo.setTradeState("03");
                break;
        }
        respVo.setCashFee(orderQueryRespVo.getPayAmount().multiply(new BigDecimal(100)).intValue());
        String sign = SignatureUtils.getWxSign(respVo, apiKey);
        respVo.setSign(sign);
        return GsonUtils.toJson(respVo, true);
    }


    /**
     * 银联商户支付回调
     */
    @RequestMapping(value = "/payNotify", method = RequestMethod.POST)
    public ChinaumsPayNotifyRespVo payNotify(@RequestBody ChinaumsPayNotifyReqVo reqVo) {
        logger.info("订单号：{}, 银联商户支付回调{}", reqVo.getOrderNo(), GsonUtils.toJson(reqVo));
        ChinaumsPayNotifyRespVo respVo = null;
        try {
            ValidationResult result = ValidationUtils.validateEntity(reqVo);
            if (result.hasErrors()) {
                respVo = new ChinaumsPayNotifyRespVo(202, result.getErrorDesc());
                return respVo;
            }
            String neetCheckSign = reqVo.getSign();
            String orderNo = reqVo.getOrderNo();
            reqVo.setSign(null);
            String rightSign = SignatureUtils.getWxSign(reqVo, apiKey);
            if (!rightSign.equals(neetCheckSign)) {
                logger.error("银联商户payNotify回调签名验证失败。 data: {}, alipayConfig : {}", GsonUtils.toJson(reqVo));
                respVo = new ChinaumsPayNotifyRespVo(201, "签名不正确");
                return respVo;
            }

            String resultCode = reqVo.getResultCode();
            if (!"SUCCESS".equals(resultCode)) {
                respVo = new ChinaumsPayNotifyRespVo(200, "ok,已确认支付未成功。");
                return respVo;
            }

            PaySuccessData paySuccessData = new PaySuccessData();
            paySuccessData.setPayTime(TimeUtils.engStringToDate(reqVo.getTimeEnd(), "yyyyMMddHHmmss"));
            paySuccessData.setPayAmount(new BigDecimal(reqVo.getCashFee()).divide(new BigDecimal(100)));
            paySuccessData.setTsn(reqVo.getReferenceNo());
            paySuccessData.setOrderNo(orderNo);
            paySuccessData.setBuyerAccount(null);
            paySuccessData.setBuyerId(null);
            paySuccessData.setBuyerBank("");
            paySuccessData.setSellerAccount(reqVo.getMerchantId());
            paySuccessData.setTradeType(TradeTypeEnum.TRADE_TYPE_UNION_PAY_POS);
            paySuccessData.setSourceType(OrderMqConstants.PAY_RESEND);
            paySuccessData.setSellerId(reqVo.getSellerId());
            TSNRecord tsnRecord = this.tsnService.insertTsnRecord(paySuccessData.getTradeType().getPayId(),
                    TsnService.DATA_TYPE_JSON, GsonUtils.toJson(reqVo), paySuccessData.getTsn(),
                    paySuccessData.getOrderNo(), TsnService.TRASACTION_PAY);

            boolean flag = orderProcessService.paySuccess(paySuccessData);
            if (flag) {
                logger.warn("orderNo={}, 银联商户回调通知成功", orderNo);
                tsnService.updateTsnRecordStatus(tsnRecord.getId(), TsnService.STATUS_PROCESS_SUCCESS);
                respVo = new ChinaumsPayNotifyRespVo(200, "ok");
                return respVo;
            } else {
                logger.warn("orderNo={}, 银联商户回调通知:处理业务失败", orderNo);
                respVo = new ChinaumsPayNotifyRespVo(202, "处理业务失败");
                return respVo;
            }
        } catch (Exception e) {
            logger.error("处理银联商户回调通知异常。requestStr=" + GsonUtils.toJson(reqVo), e);
            respVo = new ChinaumsPayNotifyRespVo(202, "处理业务失败");
            return respVo;
        }
    }

}
